]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st/theme-node: Implement extensions for accent color
authorAlice Mikhaylenko <alicem@gnome.org>
Tue, 21 Mar 2023 20:02:51 +0000 (00:02 +0400)
committerMarge Bot <marge-bot@gnome.org>
Thu, 20 Jun 2024 13:18:00 +0000 (13:18 +0000)
Add -st-accent-color and -st-fg-accent-color so that these colors can be
accessed from CSS.

Since they are often transformed in SCSS atm, add st-transparentize(),
st-mix(), st-lighten(), st-darken() that work in runtime.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2715>

src/st/st-theme-node.c

index 04f0966f108b484397bbb1d478cac3fd75181702..9ea539e31fe8ea25f4ea6e42c03fefd72dc3788a 100644 (file)
@@ -502,6 +502,20 @@ term_is_transparent (CRTerm *term)
           strcmp (term->content.str->stryng->str, "transparent") == 0);
 }
 
+static gboolean
+term_is_accent_color (CRTerm *term)
+{
+  return (term->type == TERM_IDENT &&
+          strcmp (term->content.str->stryng->str, "-st-accent-color") == 0);
+}
+
+static gboolean
+term_is_accent_fg_color (CRTerm *term)
+{
+  return (term->type == TERM_IDENT &&
+          strcmp (term->content.str->stryng->str, "-st-accent-fg-color") == 0);
+}
+
 static int
 color_component_from_double (double component)
 {
@@ -594,6 +608,180 @@ get_color_from_rgba_term (CRTerm    *term,
   return VALUE_FOUND;
 }
 
+static GetFromTermResult get_color_from_term (StThemeNode *node,
+                                              CRTerm      *term,
+                                              CoglColor   *color);
+
+static GetFromTermResult
+get_color_from_transparentize_term (StThemeNode *node,
+                                    CRTerm      *term,
+                                    CoglColor   *color)
+{
+  CRTerm *color_arg = term->ext_content.func_param;
+  CRTerm *amount_arg = color_arg->next;
+  CoglColor base_color;
+  CRNum *amount_num;
+  double amount;
+
+  if (!color_arg || !amount_arg)
+    return VALUE_NOT_FOUND;
+
+  if (get_color_from_term (node, color_arg, &base_color) != VALUE_FOUND)
+    return VALUE_NOT_FOUND;
+
+  if (amount_arg->type != TERM_NUMBER)
+    return VALUE_NOT_FOUND;
+
+  amount_num = amount_arg->content.num;
+
+  if (amount_num->type == NUM_PERCENTAGE)
+    amount = amount_num->val / 100;
+  else if (amount_num->type == NUM_GENERIC)
+    amount = amount_num->val;
+  else
+    return VALUE_NOT_FOUND;
+
+  color->red = base_color.red;
+  color->green = base_color.green;
+  color->blue = base_color.blue;
+  color->alpha = CLAMP (base_color.alpha - amount * 255, 0, 255);
+
+  return VALUE_FOUND;
+}
+
+#define LERP(a, b, t) (a + (b - a) * t)
+
+static GetFromTermResult
+get_color_from_mix_term (StThemeNode *node,
+                         CRTerm      *term,
+                         CoglColor   *color)
+{
+  CRTerm *color1_arg = term->ext_content.func_param;
+  CRTerm *color2_arg = color1_arg->next;
+  CRTerm *factor_arg = color2_arg->next;
+  CoglColor color1, color2;
+  CRNum *factor_num;
+  double factor;
+
+  if (!color1_arg || !color2_arg || !factor_arg)
+    return VALUE_NOT_FOUND;
+
+  if (get_color_from_term (node, color1_arg, &color1) != VALUE_FOUND ||
+      get_color_from_term (node, color2_arg, &color2) != VALUE_FOUND)
+    return VALUE_NOT_FOUND;
+
+  if (factor_arg->type != TERM_NUMBER)
+    return VALUE_NOT_FOUND;
+
+  factor_num = factor_arg->content.num;
+
+  if (factor_num->type == NUM_PERCENTAGE)
+    factor = factor_num->val / 100;
+  else if (factor_num->type == NUM_GENERIC)
+    factor = factor_num->val;
+  else
+    return VALUE_NOT_FOUND;
+
+  /* SCSS mix() inverts the factor for some reason */
+  factor = 1 - factor;
+
+  color->alpha = CLAMP (LERP (color1.alpha, color2.alpha, factor), 0, 255);
+
+  if (color->alpha == 0)
+    {
+      color->red = color->green = color->blue = 0;
+    }
+  else
+    {
+      color->red   = CLAMP (LERP (color1.red   * color1.alpha, color2.red   * color2.alpha, factor) / color->alpha, 0, 255);
+      color->green = CLAMP (LERP (color1.green * color1.alpha, color2.green * color2.alpha, factor) / color->alpha, 0, 255);
+      color->blue  = CLAMP (LERP (color1.blue  * color1.alpha, color2.blue  * color2.alpha, factor) / color->alpha, 0, 255);
+    }
+
+  return VALUE_FOUND;
+}
+
+static GetFromTermResult
+get_color_from_lighten_term (StThemeNode *node,
+                             CRTerm      *term,
+                             CoglColor   *color)
+{
+  CRTerm *color_arg = term->ext_content.func_param;
+  CRTerm *factor_arg = color_arg->next;
+  CoglColor base_color;
+  CRNum *factor_num;
+  double factor;
+  float hue, luminance, saturation;
+
+  if (!color_arg || !factor_arg)
+    return VALUE_NOT_FOUND;
+
+  if (get_color_from_term (node, color_arg, &base_color) != VALUE_FOUND)
+    return VALUE_NOT_FOUND;
+
+  if (factor_arg->type != TERM_NUMBER)
+    return VALUE_NOT_FOUND;
+
+  factor_num = factor_arg->content.num;
+
+  if (factor_num->type == NUM_PERCENTAGE)
+    factor = factor_num->val / 100;
+  else if (factor_num->type == NUM_GENERIC)
+    factor = factor_num->val;
+  else
+    return VALUE_NOT_FOUND;
+
+  cogl_color_to_hsl (&base_color, &hue, &saturation, &luminance);
+
+  luminance = CLAMP (luminance + factor, 0, 1);
+
+  cogl_color_init_from_hsl (color, hue, saturation, luminance);
+  color->alpha = base_color.alpha;
+
+  return VALUE_FOUND;
+}
+
+static GetFromTermResult
+get_color_from_darken_term (StThemeNode *node,
+                            CRTerm      *term,
+                            CoglColor   *color)
+{
+  CRTerm *color_arg = term->ext_content.func_param;
+  CRTerm *factor_arg = color_arg->next;
+  CoglColor base_color;
+  CRNum *factor_num;
+  double factor;
+  float hue, luminance, saturation;
+
+  if (!color_arg || !factor_arg)
+    return VALUE_NOT_FOUND;
+
+  if (get_color_from_term (node, color_arg, &base_color) != VALUE_FOUND)
+    return VALUE_NOT_FOUND;
+
+  if (factor_arg->type != TERM_NUMBER)
+    return VALUE_NOT_FOUND;
+
+  factor_num = factor_arg->content.num;
+
+  if (factor_num->type == NUM_PERCENTAGE)
+    factor = factor_num->val / 100;
+  else if (factor_num->type == NUM_GENERIC)
+    factor = factor_num->val;
+  else
+    return VALUE_NOT_FOUND;
+
+  cogl_color_to_hsl (&base_color, &hue, &saturation, &luminance);
+  color->alpha = base_color.alpha;
+
+  luminance = CLAMP (luminance - factor, 0, 1);
+
+  cogl_color_init_from_hsl (color, hue, saturation, luminance);
+  color->alpha = base_color.alpha;
+
+  return VALUE_FOUND;
+}
+
 static GetFromTermResult
 get_color_from_term (StThemeNode  *node,
                      CRTerm       *term,
@@ -614,6 +802,18 @@ get_color_from_term (StThemeNode  *node,
       *color = TRANSPARENT_COLOR;
       return VALUE_FOUND;
     }
+  /* St-specific extension: -st-accent-color */
+  else if (term_is_accent_color (term))
+    {
+      st_theme_context_get_accent_color (node->context, color, NULL);
+      return VALUE_FOUND;
+    }
+  /* St-specific extension: -st-accent-fg-color */
+  else if (term_is_accent_fg_color (term))
+    {
+      st_theme_context_get_accent_color (node->context, NULL, color);
+      return VALUE_FOUND;
+    }
   /* rgba () colors - a CSS3 addition, are not supported by libcroco,
    * but they are parsed as a "function", so we can emulate the
    * functionality.
@@ -626,6 +826,42 @@ get_color_from_term (StThemeNode  *node,
     {
       return get_color_from_rgba_term (term, color);
     }
+  /* St-specific extension: st-transparentize() */
+  else if (term->type == TERM_FUNCTION &&
+           term->content.str &&
+           term->content.str->stryng &&
+           term->content.str->stryng->str &&
+           strcmp (term->content.str->stryng->str, "st-transparentize") == 0)
+    {
+      return get_color_from_transparentize_term (node, term, color);
+    }
+  /* St-specific extension: st-mix() */
+  else if (term->type == TERM_FUNCTION &&
+           term->content.str &&
+           term->content.str->stryng &&
+           term->content.str->stryng->str &&
+           strcmp (term->content.str->stryng->str, "st-mix") == 0)
+    {
+      return get_color_from_mix_term (node, term, color);
+    }
+  /* St-specific extension: st-lighten() */
+  else if (term->type == TERM_FUNCTION &&
+           term->content.str &&
+           term->content.str->stryng &&
+           term->content.str->stryng->str &&
+           strcmp (term->content.str->stryng->str, "st-lighten") == 0)
+    {
+      return get_color_from_lighten_term (node, term, color);
+    }
+  /* St-specific extension: st-darken() */
+  else if (term->type == TERM_FUNCTION &&
+           term->content.str &&
+           term->content.str->stryng &&
+           term->content.str->stryng->str &&
+           strcmp (term->content.str->stryng->str, "st-darken") == 0)
+    {
+      return get_color_from_darken_term (node, term, color);
+    }
 
   status = cr_rgb_set_from_term (&rgb, term);
   if (status != CR_OK)